﻿// Decompiled with JetBrains decompiler
// Type: Microsoft.InfoCards.GetTokenRequest
// Assembly: infocard, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// MVID: 8E14765A-6610-409A-BA36-099A0642905D
// Assembly location: E:\git\ALLIDA\windll\infocard.exe

using Microsoft.InfoCards.Diagnostics;
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Security.Principal;
using System.ServiceModel.Description;
using System.Text;
using System.Threading;

namespace Microsoft.InfoCards
{
  internal class GetTokenRequest : ClientUIRequest
  {
    private object m_createSecurityTokenDoneMonitor = new object();
    private bool m_isProcessingComplete = true;
    private InfoCardPolicy[] m_policyChain;
    private InfoCardPolicy m_policy;
    private TokenDescriptor m_token;
    private ITokenFactory m_tokenFactory;
    private LedgerEntry m_ledgerEntry;
    private InfoCard m_selectedCard;
    private Recipient m_recipient;
    private bool m_userProceededToCreateToken;

    public GetTokenRequest(
      Process callingProcess,
      WindowsIdentity callingIdentity,
      InfoCardUIAgent uiAgent,
      IntPtr rpcHandle,
      Stream inArgs,
      Stream outArgs)
      : base(callingProcess, callingIdentity, uiAgent, rpcHandle, inArgs, outArgs, InfoCardUIAgent.CallMode.GetToken, ExceptionList.AllNonFatal)
    {
    }

    public TokenDescriptor Token
    {
      get
      {
        return this.m_token;
      }
    }

    public InfoCardPolicy Policy
    {
      get
      {
        return this.m_policy;
      }
      protected set
      {
        this.m_policy = value;
      }
    }

    protected Recipient GetRecipient()
    {
      if (this.m_recipient == null)
        this.m_recipient = new Recipient(this.m_policy.Recipient, false, this.m_policy.PrivacyPolicyVersion);
      return this.m_recipient;
    }

    protected override void OnMarshalInArgs()
    {
      BinaryReader reader = (BinaryReader) new InfoCardBinaryReader(this.InArgs, Encoding.Unicode);
      int length = reader.ReadInt32();
      if (length <= 0 || length > 50)
        throw InfoCardTrace.ThrowHelperError((Exception) new InfoCardArgumentException(SR.GetString("InvalidPolicyLength")));
      this.m_policyChain = new InfoCardPolicy[length];
      for (int index = 0; index < length; ++index)
      {
        string recipientXml = Utility.DeserializeString(reader);
        string issuerXml = Utility.DeserializeString(reader);
        string policyXml = Utility.DeserializeString(reader);
        string privacyUrl = Utility.DeserializeString(reader);
        uint privacyVersion = reader.ReadUInt32();
        bool isManaged = reader.ReadBoolean();
        this.m_policyChain[index] = PolicyFactory.CreatePolicyForGetTokenRequest(reader, recipientXml, issuerXml, policyXml, isManaged);
        if (index == 0)
          this.m_policyChain[index].SetRecipientInfo(this.m_policyChain[0].ImmediateTokenRecipient, privacyUrl, privacyVersion);
        else
          this.m_policyChain[index].SetRecipientInfo(this.m_policyChain[0].ImmediateTokenRecipient, this.m_policyChain[0].PrivacyPolicyLink, this.m_policyChain[0].PrivacyPolicyVersion);
      }
      int index1 = length - 1;
      if (this.m_policyChain[index1].IsManaged)
      {
        if (index1 == 0)
          throw InfoCardTrace.ThrowHelperError((Exception) new InfoCardArgumentException(SR.GetString("InvalidPolicyLength")));
        --index1;
      }
      this.m_policy = this.m_policyChain[index1];
      this.m_policy.Validate();
    }

    protected override void OnProcess()
    {
      this.StartAndWaitForUIAgent();
    }

    protected override void OnMarshalOutArgs()
    {
      BinaryWriter bwriter = new BinaryWriter(this.OutArgs, Encoding.Unicode);
      this.m_token.Write(bwriter);
      SymmetricAlgorithm symmetricProof = this.m_token.SymmetricProof;
      (symmetricProof != null ? CryptoSession.Create(this.CallerProcess, this.m_token.ExpirationTime, this.RequestorIdentity, symmetricProof.Key) : CryptoSession.Create(this.CallerProcess, this.m_token.ExpirationTime, this.RequestorIdentity, this.GetPrivateCryptography())).Write(bwriter);
    }

    protected RSACryptoServiceProvider GetPrivateCryptography()
    {
      return this.m_selectedCard.GetPrivateCryptography(this.GetRecipient().RecipientId);
    }

    protected override void OnDisposeAsUser()
    {
      base.OnDisposeAsUser();
      if (this.m_token == null)
        return;
      this.m_token.Dispose();
      this.m_token = (TokenDescriptor) null;
    }

    public void CancelSelectCard()
    {
      this.m_userProceededToCreateToken = false;
      this.m_isProcessingComplete = true;
    }

    public int SelectCard(InfoCard card, bool isSelfIssued)
    {
      lock (this.m_createSecurityTokenDoneMonitor)
      {
        while (this.m_userProceededToCreateToken && !this.m_isProcessingComplete)
          Monitor.Wait(this.m_createSecurityTokenDoneMonitor);
        this.m_userProceededToCreateToken = false;
        this.m_isProcessingComplete = false;
        int index1 = 0;
        TokenCreationParameter parameter = (TokenCreationParameter) null;
        ServiceEndpoint endPoint = (ServiceEndpoint) null;
        IWebProxy proxy = (IWebProxy) null;
        StoreConnection connection = StoreConnection.GetConnection();
        try
        {
          card.Connection = connection;
          if (!isSelfIssued)
          {
            if (1 == card.CreationParameters.Count)
            {
              index1 = 0;
              parameter = card.CreationParameters[index1];
            }
            else
            {
              for (int index2 = 0; index2 < card.CreationParameters.Count; ++index2)
              {
                try
                {
                  endPoint = RemoteTokenFactory.DoMexExchange(card.CreationParameters[index2], this.UserProxy);
                  index1 = index2;
                  parameter = card.CreationParameters[index1];
                  break;
                }
                catch (TrustExchangeException ex)
                {
                  if (index2 == card.CreationParameters.Count - 1)
                    throw InfoCardTrace.ThrowHelperError((Exception) new TrustExchangeException(SR.GetString("InvalidServiceUri")));
                }
              }
            }
            proxy = this.UserProxy;
          }
        }
        finally
        {
          connection.Close();
        }
        this.m_tokenFactory = TokenFactoryFactory.Create(card, parameter, endPoint, proxy);
        this.m_selectedCard = card;
        return index1;
      }
    }

    public void CancelCreateSecurityToken()
    {
      if (this.m_tokenFactory != null)
        this.m_tokenFactory.Abort();
      this.m_userProceededToCreateToken = true;
    }

    public DisplayToken CreateSecurityToken(
      TokenFactoryCredential credential,
      bool discloseOptional)
    {
      lock (this.m_createSecurityTokenDoneMonitor)
      {
        try
        {
          this.m_ledgerEntry = this.GetLedgerEntry();
          if (this.m_token != null)
          {
            this.m_token.Dispose();
            this.m_token = (TokenDescriptor) null;
          }
          using (credential)
            this.m_token = this.m_tokenFactory.CreateToken(this.m_selectedCard, credential, this.m_policy, discloseOptional);
          this.m_ledgerEntry.DisclosureDate = DateTime.UtcNow;
          this.m_ledgerEntry.DisclosedClaims = new string[this.m_token.DisclosedClaims.Count];
          for (int index = 0; index < this.m_token.DisclosedClaims.Count; ++index)
            this.m_ledgerEntry.DisclosedClaims[index] = this.m_token.DisclosedClaims[index];
          Array.Clear((Array) this.m_selectedCard.Key, 0, this.m_selectedCard.Key.Length);
          return this.m_token.DisplayToken;
        }
        finally
        {
          this.m_isProcessingComplete = true;
          this.m_userProceededToCreateToken = true;
          Monitor.Pulse(this.m_createSecurityTokenDoneMonitor);
        }
      }
    }

    private LedgerEntry GetLedgerEntry()
    {
      LedgerEntry entry = (LedgerEntry) null;
      StoreConnection connection = StoreConnection.GetConnection();
      try
      {
        entry = this.m_selectedCard.TryGetLedgerEntry(connection, this.m_policy.Recipient.GetIdentifier());
        if (entry == null)
          entry = this.m_selectedCard.CreateLedgerEntry(this.GetRecipient(), this.m_policy.ImmediateTokenRecipient.GetOrganizationIdentifier());
        else
          this.m_selectedCard.CheckAndUpdateLedgerEntry(entry, this.m_policy.ImmediateTokenRecipient.GetOrganizationIdentifier());
      }
      finally
      {
        connection.Close();
      }
      return entry;
    }

    public void SaveLedgerEntry()
    {
      StoreConnection connection = StoreConnection.GetConnection();
      try
      {
        connection.BeginTransaction();
        try
        {
          this.m_ledgerEntry.Save(connection);
          connection.CommitTransaction();
        }
        catch
        {
          connection.RollbackTransaction();
          throw;
        }
      }
      finally
      {
        connection.Close();
      }
    }

    public enum TrustDecision : byte
    {
      NoTrustDecision,
      IsTrusted,
      IsNotTrusted,
    }
  }
}
